#!/usr/bin/env python
# coding: utf-8
"""
准备工作：需要把705upgrade目录放在脚本执行的路径下
"""

import re
import os
import time
import datetime
import string
from onshs.ne.tnxxx.tnxxxcfg_basecase import *

log_node_summary = "rfc1323_summary"
log_node_fail = "rfc1323_fail"
log_node_success = "rfc1323_success"
log_node_check_fail = "rfc1323_check_fail"
log_node_check_success = "rfc1323_check_success"

log_file_not_existed = "the file:%s isn't existed\n"
log_connect_fail = "connect ip:%s failed\n"
log_connect_slot_fail = "connect ip:%s slot:%s failed\n"

log_check_fail = "check ip:%s slot:%s rfc1323 timestamp wa failed\n"
log_execute_fail = "execute ip:%s slot:%s rfc1323 timestamp wa failed\n"

log_check_success = "check ip:%s slot:%s rfc1323 timestamp wa success\n"
log_execute_success = "execute ip:%s slot:%s rfc1323 timestamp wa success\n"

log_summary_success = "ip:%s rfc1323 timestamp wa success"
log_summary_fail = "ip:%s rfc1323 timestamp wa failed"

class TestCase(TnxxxCfg_BaseCase):
    """
    TestCase
    """
    OPTIONS = [
        {
            'opt' : '--cfgfile',
            'dest': 'cfgfile',
            'metavar' : 'CFGFILE',
            'help' : 'the file of ip list configuration',
            'required' : False,
            'default' : "ip.txt"
        },
        {
            'opt' : '--timestamp',
            'dest': 'timestamp',
            'metavar' : 'TIMESTAMP',
            'help' : 'the configuration of timestamp',
            'required' : False,
            'default' : "disable"
        },   
    ]     
    
    def info_init(self):
        self.info_dic = {}     
              
        return True 
    
    #以node为关键字，把信息保存到info_dic[node]中。
    def info_show(self, node, info):
        node = self.timestamp + r'_' + node
        if not self.info_dic.has_key(node):
            self.info_dic[node] = ""
        self.info_dic[node] += info + '\n'        
        return True    
            
    def info_file_save(self, ip):
        path = os.getcwd()+'//'
        
        for node in self.info_dic:
            info_list = open(path+node+'_'+self.worktime+'.txt','a')            
            info_list.write(self.info_dic[node])
            info_list.close()
            
        return True
    
    def get_iplist(self):
        iplist_filted = []                
        if os.path.isfile(os.getcwd()+r'/'+ self.iplistfile):
            iplist = open(os.getcwd()+r'/'+ self.iplistfile)            
        else:
            self.info_show(self.log_node_fail, self.log_file_not_existed%(self.iplistfile))            
            return iplist_filted 
        
        for line in iplist:
            if re.match(r'^\s*$', line) is not None : continue # 忽略空白行
            if re.match(r'^\s*#', line) is not None : continue # 忽略注释行            
            iplist_filted.append(line.strip('\n'))        
            
        iplist.close()
        
        return iplist_filted
    
    def get_slotlist_from_cardtype(self, cardtype_list):
        """
        cardtype_list = [cardtype(str),...]       
        """
        
        query_slotlist = [1,2,3,4,5,6,7,8]
        slotlist = []
                    
        rtn = self.tnxxx.send_rtn_str("show card", self.get_ne_ip(0), 0, CLI_PORT)
        card_info_list = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?stat:\s+\w+\s+(?:--More--\s+)?Card:\s+(\w+)\s+", rtn, re.I)
        
        for card_info in card_info_list:
            slot = int(card_info[0])
            if slot not in query_slotlist : continue            
           
            card_name = card_info[1].upper()
            
            for cardtype in cardtype_list:                
                if cardtype == card_name:
                    slotlist.append(slot)
                    break
            else:
                continue        
            
        return slotlist
    
    def expect_reg_or_mem_value(self, slot, addr, expectvalue):
        """
        slot(int)                     --槽位号
        addr(str)                     --地址
        expectvalue(str)              --期望值，字符串，内容为16进制的值. 例如'0x409d1378'.
        如果读取地址得到的值和期望值相同，返回true，否则返回false.
        """       
        rtn = self.tnxxx.send_rtn_str("%s"%addr, self.get_ne_ip(0), slot, DEV_PORT)  
        rtn_str = None
        rtn_str = re.search(r'value = \d+',rtn)
        if None == rtn_str:
            self.info_show(log_node_fail, log_connect_slot_fail%(self.get_ne_ip(0),slot))
            return False
        else:
            addr_value = rtn_str.group()[8:]
            
        if hex(int(addr_value)) == expectvalue:            
            return True
        else:            
            return False

    def write_reg_or_mem_value(self, slot, command, value):
        """
        slot(int)                     --槽位号
        command(str)                  --命令
        value(str)                    --值，字符串，内容为16进制的值. 例如'48000004'.
        如果读取地址得到的值和期望值相同，返回true，否则返回false.
        """
        
        cmd_list = [        
        ["%s"%command, None],
        ["%s"%value, None],
        ['.', "", 2],
        ]
        
        cfg_info_list = [[cmd_list, {}, 0, [slot,DEV_PORT]],]        
        self.run(cfg_info_list)        
        
        if slot == 3 or slot == 4:
            addr = "*(tcp_input + 0xb28)"
            if "enable" == self.timestamp:
                expectvalue = '0x409d1378'                        
            elif "disable" == self.timestamp:
                expectvalue = "0x48000004"
        else:
            addr = "*(tcp_input + 0xb34)"
            if "enable" == self.timestamp:
                expectvalue = '0x409d1388'                        
            elif "disable" == self.timestamp:
                expectvalue = "0x48000004"            
        
        
        if True == self.expect_reg_or_mem_value(slot, addr, expectvalue):
            self.info_show(log_node_success, log_execute_success%(self.get_ne_ip(0),slot))
            return True
        else:
            self.info_show(log_node_fail, log_execute_fail%(self.get_ne_ip(0),slot))
            return False
        
    def get_master_opca(self, slot, command, value):
        query_masterppc_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        rtn_str = None
        masterppc = 0
        rtn_str = self.tnxxx.send_rtn_str(query_masterppc_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str):         
            self.info_show(log_node_fail, self.log_connect_fail%(ip))
            self.info_show(log_node_summary, self.log_summary_fail%(ip))             
        else:
            masterppc = int(re.findall('\d',rtn_str)[0])
            
        return masterppc
       
    def _execute(self):                        
        self.info_init()
        
        worktime = str(datetime.datetime.now())
        self.worktime = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.iplistfile = self.options.cfgfile
        self.timestamp = self.options.timestamp
        self.work_path = os.getcwd()
        cardtype_list = ['OPCA', 'N64F01', 'N16F01']
        
        ip_list = self.get_iplist()         
        
        for ip in ip_list:            
            self.set_ne_ip(0, ip)         
            
            ip_summary_flag = True
            
            slot_list = self.get_slotlist_from_cardtype(cardtype_list)
            if [] == slot_list:
                self.info_show(log_node_fail, log_connect_fail%(self.get_ne_ip(0)))
                ip_summary_flag = False                
                            
            for slot in slot_list:
                if slot == 3 or slot == 4:
                    code_addr = "*(tcp_input + 0xb28)"                    
                    write_command = 'm tcp_input + 0xb28,4'
                    if "enable" == self.timestamp:
                        write_value = '409d1378'                        
                    elif "disable" == self.timestamp:
                        write_value = '48000004'
                else:
                    code_addr = "*(tcp_input + 0xb34)"                    
                    write_command = 'm tcp_input + 0xb34,4'
                    if "enable" == self.timestamp:
                        write_value = '409d1388'                        
                    elif "disable" == self.timestamp:
                        write_value = '48000004'
                
                expect_value = "0x48000004"   
                        
                if False == self.expect_reg_or_mem_value(slot,code_addr,expect_value):
                    self.info_show(log_node_check_fail, log_check_fail%(self.get_ne_ip(0),slot))                     
                else:
                    self.info_show(log_node_check_success, log_check_success%(self.get_ne_ip(0),slot))  
                    
                if "enable" == self.timestamp or "disable" == self.timestamp:
                    if False == self.write_reg_or_mem_value(slot,write_command,write_value):
                        ip_summary_flag = False
                        break
            
            if True == ip_summary_flag:                
                self.info_show(log_node_summary, log_summary_success%(ip))
            else:
                self.info_show(log_node_summary, log_summary_fail%(ip)) 
            
            self.tnxxx.disconnect()
           
        worktime = str(datetime.datetime.now())
        self.worktime_end = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.info_show(log_node_summary, "The rfc1323 wa operation begin time %s "%(self.worktime))
        self.info_show(log_node_summary, "The rfc1323 wa operation end time %s "%(self.worktime_end))
        
        ip = '0.0.0.0'
        self.info_file_save(ip) 
        return True
    
if __name__ == "__main__" :
    case = TestCase()
    case.execute()